package com.webshooter;

import com.webshooter.entity.EntityContainer;
import com.webshooter.decoder.JoinCommand;
import com.webshooter.decoder.Command;
import com.webshooter.decoder.CommandDecoder;
import com.webshooter.decoder.KeyPressCommand;
import com.webshooter.decoder.KeyUpCommand;
import com.webshooter.decoder.MouseDownCommand;
import com.webshooter.decoder.MouseUpCommand;
import com.webshooter.decoder.UpdatePlayerAngleCommand;
import com.webshooter.entity.Entity;
import com.webshooter.encoder.CreateEntityEvent;
import com.webshooter.entity.Entity.GameLogicState;
import com.webshooter.entity.Entity.MovementState;
import com.webshooter.math.Vector;
import com.webshooter.systems.CombatSystem;
import com.webshooter.systems.MovementSystem;
import java.io.IOException;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import javax.inject.Inject;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;

@ServerEndpoint(
        value = "/echo",
        decoders = {CommandDecoder.class})
public class ShooterEndpoint {

    @Inject
    private ClientUpdater clientUpdater;
    @Inject
    private EntityContainer entityContainer;
    @Inject
    private MovementSystem movementSystem;
    @Inject
    private CombatSystem combatSystem;
    static Queue<Session> queue = new ConcurrentLinkedQueue<>();

    @OnOpen
    public void openConnection(Session session) throws Exception {
        queue.add(session);

        for (Entity currentEntity : entityContainer.getAllEntities()) {

            clientUpdater.addEvent(new CreateEntityEvent(currentEntity));
        }
    }

    @OnClose
    public void closedConnection(Session session) {
        queue.remove(session);
    }

    @OnError
    public void error(Session session, Throwable t) {
        queue.remove(session);
    }

    @OnMessage
    public void onMessage(Session session, Command command) throws Exception {

        if (command instanceof JoinCommand) {
            JoinCommand joinCommand = (JoinCommand) command;
            Entity entity = entityContainer.findEntityByName(joinCommand.getName());
            if (entity == null) {
                entity = new Entity(joinCommand.getName());
                Vector pos = combatSystem.getRandomSpawnPosition();
                entity.pos.x = pos.x;
                entity.pos.y = pos.y;
                entity.gameLogicState = GameLogicState.ALIVE;
                entity.moveState = MovementState.STAND;

                clientUpdater.addEvent(new CreateEntityEvent(entity));

                entityContainer.add(entity);
            }

        } else if (command instanceof KeyPressCommand) {
            movementSystem.keyPress((KeyPressCommand) command);
        } else if (command instanceof KeyUpCommand) {
            movementSystem.keyUp((KeyUpCommand) command);
        } else if (command instanceof UpdatePlayerAngleCommand) {
            movementSystem.updatePlayerAngle((UpdatePlayerAngleCommand) command);
        } else if (command instanceof MouseDownCommand) {
            combatSystem.mouseDown((MouseDownCommand) command);
        } else if (command instanceof MouseUpCommand) {
            combatSystem.mouseUp((MouseUpCommand) command);
        } else {
            throw new IllegalArgumentException("Command not supported!");
        }
    }

    public static synchronized void sendAll(String msg) {
        try {
            for (Session session : queue) {
                if (session.isOpen()) {
                    session.getBasicRemote().sendText(msg);
                }
            }
        } catch (IOException e) {
        }
    }
}
